Tinc GUI

Android port of tinc VPN with basic GUI

Download .zip Download .tar.gz View on GitHub

Welcome to Tinc GUI for Android home page.

Tinc is an open source peer to peer VPN daemon. Find more information at http://www.tinc-vpn.org.

Tinc GUI for Android is a (slightly modified) cross-compiled version of tincd for Arm, associated with a basic GUI for daemon management.

Where to get it?

Preferred way to get Tinc GUI is via Google Play.

You may also get directly the APK for manual installation:
Latest Tinc GUI version (historical versions are available on GitHub)

How does it work?

As this is a simple GUI around the original tincd daemon, please refer to the official documentation for the configuration.

The easiest solution is to build your configuration and store it on your external SD card. Because Android devices usually mount it with noexec flag, a new option has been added to tinc's configuration file, in order to specify the script interpreter to use for configuration scripts (instead of having them executable):

# Use sh to execute all configuration scripts
ScriptsInterpreter = /system/bin/sh

FAQ

Why does this application need SuperUser rights?

It doesn't really need them by itself (there's an option to disable it). However tincd daemon will most probably need super user rights to work properly: access to TUN/TAP device is usually restricted to root.

Do you have any configuration example?

The configuration follows standard tinc's one. For an easier start, here's mine.
It uses switch mode on CM 10.1 (thus TUN device is /dev/tun), and routes all the traffic through the VPN (using host-up file).

tinc.conf

Name = android
AddressFamily = ipv4
ConnectTo = another_peer
Device = /dev/tun
DeviceType = tap
Mode = switch
KeyExpire = 3600
Interface = tap0
PrivateKeyFile = /sdcard/tinc/vpn/rsa_key.priv
ScriptsInterpreter = /system/bin/sh

tinc-up

#!/system/bin/sh
ifconfig $INTERFACE 10.0.0.130
echo 1 > /proc/sys/net/ipv4/conf/$INTERFACE/rp_filter

hosts/another_peer

Address = another_peer.org
Subnet = 10.0.0.0/24

-----BEGIN RSA PUBLIC KEY-----
...
-----END RSA PUBLIC KEY-----

hosts/another_peer-up

#!/system/bin/sh 
echo $REMOTEADDRESS
echo $INTERFACE 
VPN_GATEWAY=10.0.0.254
ORIGINAL_GATEWAY=`ip route show | grep ^default | cut -d ' ' -f 2-5`

ip route add $REMOTEADDRESS $ORIGINAL_GATEWAY 
ip route add $VPN_GATEWAY dev $INTERFACE 
ip route add 0.0.0.0/1 via $VPN_GATEWAY dev $INTERFACE 
ip route add 128.0.0.0/1 via $VPN_GATEWAY dev $INTERFACE

hosts/another_peer-down

#!/system/bin/sh
VPN_GATEWAY=10.0.0.254
ORIGINAL_GATEWAY=`ip route show | grep ^default | cut -d ' ' -f 2-5`

ip route del $REMOTEADDRESS $ORIGINAL_GATEWAY 
ip route del $VPN_GATEWAY dev $INTERFACE 
ip route del 0.0.0.0/1 via $VPN_GATEWAY dev $INTERFACE 
ip route del 128.0.0.0/1 via $VPN_GATEWAY dev $INTERFACE

Android 5.0 / Lollipop

Lollipop uses several routing tables, depending on the available interfaces and/or users. This makes VPN re-routing a bit trickier. Here is my default configuration when running CM 12 on wifi connection:

root@hammerhead:/ # ip rule show
0:      from all lookup local
10000:  from all fwmark 0xc0000/0xd0000 lookup legacy_system
13000:  from all fwmark 0x10063/0x1ffff lookup local_network
13000:  from all fwmark 0x10064/0x1ffff lookup wlan0
14000:  from all oif wlan0 lookup wlan0
15000:  from all fwmark 0x0/0x10000 lookup legacy_system
16000:  from all fwmark 0x0/0x10000 lookup legacy_network
17000:  from all fwmark 0x0/0x10000 lookup local_network
19000:  from all fwmark 0x64/0x1ffff lookup wlan0
22000:  from all fwmark 0x0/0xffff lookup wlan0
23000:  from all fwmark 0x0/0xffff uidrange 0-0 lookup main
32000:  from all unreachable

root@hammerhead:/ # ip route show
# As in your example, there's no default route here
192.168.0.0/24 dev wlan0  proto kernel  scope link  src 192.168.0.42

root@hammerhead:/ # ip route show table wlan0
#But here you find it in the wlan0 table
default via 192.168.0.253 dev wlan0  proto static
192.168.0.0/24 dev wlan0  proto static  scope link

Therefore, host-up/down scripts must be adapted. Here is a working example:

hosts/another_peer-up

#!/system/bin/sh 
echo $REMOTEADDRESS
echo $INTERFACE 
VPN_GATEWAY=10.0.0.254
# Fetch the first default gateway from the current routing tables
ORIGINAL_GATEWAY=$(for a in $(ip rule show | grep lookup | sed -r 's/.* lookup ([^ ]+).*/\1/'); do ip route show table $a | grep ^default | cut -d ' ' -f 2-5; done | head -1)
echo $ORIGINAL_GATEWAY

# Use new routing table 100, to have higher priority than lollipop's ones
ip rule add prio 100 from all lookup 100
ip route add table 100 $REMOTEADDRESS $ORIGINAL_GATEWAY 
ip route add table 100 $VPN_GATEWAY dev $INTERFACE 
ip route add table 100 0.0.0.0/1 via $VPN_GATEWAY dev $INTERFACE 
ip route add table 100 128.0.0.0/1 via $VPN_GATEWAY dev $INTERFACE

hosts/another_peer-down

#!/system/bin/sh
VPN_GATEWAY=10.0.0.254

ip rule del from all lookup 100
ip route del table 100 $REMOTEADDRESS
ip route del table 100 $VPN_GATEWAY dev $INTERFACE 
ip route del table 100 0.0.0.0/1 via $VPN_GATEWAY dev $INTERFACE 
ip route del table 100 128.0.0.0/1 via $VPN_GATEWAY dev $INTERFACE

I'm getting "/dev/net/tun not found" error when starting tinc

Depending on your ROM, the path to TUN/TAP device might be different. Use the Device directive in tinc.conf to specify the correct one (eg. "Device = /dev/tun for CM ROMs).

I'm getting "Reading RSA private key file `xxx' failed" error when starting tinc

This happens when the private key can't be read for some reason. Regenerate it and copy it to the device properly.

What are the supported CPU architectures?

ARM and x86 only for the time being.

Is it working?

Used to work very well on my SGS2 i9100, under CyanogenMod 9. Now running on Nexus 4 and Oneplus One with CM 11 (Android 4.4.4) without a glitch. Waiting for more feedback.

Is it possible to start/stop the service from other applications (such as tasker)?

Yes, since version 0.9.9. This can be done using the custom actions of TincdService.
Package: org.poirsouille.tinc_gui
Class: org.poirsouille.tinc_gui.TincdService
Actions: org.poirsouille.tinc_gui.TincdService.START / org.poirsouille.tinc_gui.TincdService.STOP

You may test this functionality using ADB to send the intents:

adb shell am startservice -a org.poirsouille.tinc_gui.TincdService.START org.poirsouille.tinc_gui/.TincdService
adb shell am startservice -a org.poirsouille.tinc_gui.TincdService.STOP org.poirsouille.tinc_gui/.TincdService

Is it free?

Yes, it's even released under GPLv3. Source code is available on GitHub. However if you like this application and want to support it, you might donate to the author.

I also gladly accept bitcoins (1GnaV352mdeo5wSMtB2mCcoe2MB4WEqjnJ) and litecoins (LfQx5F9zhvjvjRE5H87BsBqWbRr2BrY3W8).